package me.youline.dataServer.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import me.youline.dataServer.ConfigConstants;
import me.youline.dataServer.dao.UserTokenDAO;
import me.youline.dataServer.entity.UserToken;

import org.perf4j.aop.Profiled;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component("userTokenJdbcDAOImpl")
public class UserTokenJdbcDAOImpl implements UserTokenDAO {
	
	@Autowired
	private JdbcTemplate jdbcTemplate;

	private static final String TABLE_NAME = "yline_base_userToken";

	private static final String INSERT_TOKEN_SQL = "insert into " + TABLE_NAME
			+ "(token,userId,userName,expiredAt) values(?,?,?,?)";

	private static final String DELETE_TOKEN_SQL = "delete from " + TABLE_NAME
			+ " where token = ?";

	private static final String UPDATE_EXPIREDAT_SQL = " update " + TABLE_NAME
			+ " set expiredAt = ? where token = ? ";

	private static final String QUERY_USERTOKEN_SQL = "select * from "
			+ TABLE_NAME + " where  token = ? ";
	
	private static final String QUERY_USERTONEKN_BY_USERNAME_SQL = "select * from "+TABLE_NAME+" where userName = ?";
	
	private static final String DELETE_INVALID_USERTOKEN_SQL = " delete from " +TABLE_NAME+ " where expiredAt <= ?"; 
	
	private static final String LOAD_ALL_TOKEN_SQL = "select * from "+TABLE_NAME+" limit ?";
	
	private static final String QUERY_TOKEN_BY_USERID = "select * from " + TABLE_NAME + " where userId = ? ";
	
	private static final RowMapper<UserToken> ROW_MAPPER = new RowMapper<UserToken>() {

		@Override
		public UserToken mapRow(ResultSet rs, int rowNum) throws SQLException {
			UserToken token = new UserToken();
			token.setCreateTime(rs.getDate("createTime"));
			token.setExpiredAt(rs.getLong("expiredAt"));
			token.setUserId(rs.getLong("userId"));
			token.setToken(rs.getString("token"));
			token.setUserName(rs.getString("userName"));
			return token;
		}
	};

	@Override
	@Transactional
	@Profiled(tag="dao-数据库存储token")
	public void save(UserToken token) {
		jdbcTemplate.update(INSERT_TOKEN_SQL, token.getToken(),
				Long.valueOf(token.getUserId()), token.getUserName(),token.getExpiredAt());
	}

	@Override
	@Transactional
	@Profiled(tag="dao-数据库删除token")
	public boolean deleteUserToken(String token) {
		return jdbcTemplate.update(DELETE_TOKEN_SQL, token) > 0;
	}

	@Override
	@Transactional
	@Profiled(tag="dao-数据库更新token过期时间")
	public boolean updateExpiredAtTime(String token, Date time) {
		return jdbcTemplate.update(UPDATE_EXPIREDAT_SQL, new Object[]{time.getTime(),token}) > 0;
	}

	public UserToken getUserTokenByTokenStr(String token) {
		try {
			return jdbcTemplate.queryForObject(QUERY_USERTOKEN_SQL, new Object[] { token },ROW_MAPPER);
		} catch (DataAccessException e) {
			if(  e instanceof EmptyResultDataAccessException){
				return null;
			}
			throw e;
		}
	}

	@Override
	@Transactional
	@Profiled(tag="dao-数据库删除过期token")
	public void deleteExpiredToken(Date date) {
		jdbcTemplate.update(DELETE_INVALID_USERTOKEN_SQL, date.getTime());
	}

	@Override
	@Profiled(tag="dao-数据库根据用户名获取token")
	public UserToken getUserTokenByUserName(String userName) {
		try {
			return jdbcTemplate.queryForObject(QUERY_USERTONEKN_BY_USERNAME_SQL, new Object[]{userName},ROW_MAPPER);
		} catch(EmptyResultDataAccessException e) {
			return null;
		}
	}

	@Override
	@Profiled(tag="dao-数据库加载所有token")
	public List<UserToken> loadAllUserToken() {
		 List<UserToken> list =  jdbcTemplate.query(LOAD_ALL_TOKEN_SQL, new Object[]{ConfigConstants.TOKEN_CACHE_NUMS}, ROW_MAPPER);
		 if(list == null){
			 return Collections.emptyList();
		 }
		 return list;
	}

	@Override
	public UserToken getUserTokenTokenByUserId(Long userId) {
		try {
			return jdbcTemplate.queryForObject(QUERY_TOKEN_BY_USERID,new Object[]{ userId }, ROW_MAPPER);
		} catch (EmptyResultDataAccessException e) {
			return null;
		}
	}
	
}
